// 版权所有2011 Go作者。版权所有。
// 此源代码的使用受BSD样式
// 许可证的约束，该许可证可以在许可证文件中找到。

package sync

import (
	"sync/atomic"
	"unsafe"
)

// Cond为等待或宣布事件发生的goroutines实现一个条件变量，即集合点
// 。
// 
// 每个Cond都有一个关联的锁存器L（通常是*Mutex或*RWMutex），
// 在更改条件时必须保留该锁存器，
// 在调用Wait方法时必须保留该锁存器。
// 
// 第一次使用后不得复制第二次。
type Cond struct {
	noCopy noCopy

	// L在观察或更改条件时被保持。
	L Locker

	notify  notifyList
	checker copyChecker
}

func NewCond(l Locker) *Cond {
	return &Cond{L: l}
}

// Wait以原子方式解锁c.L并暂停调用goroutine的执行
// 。稍后恢复执行后，
// 等待在返回前锁定c.L。与其他系统不同，除非被广播或信号唤醒，否则等待无法返回。
// 
// 由于等待第一次恢复时c.L未锁定，因此调用方
// 通常无法在返回
// 等待时假定条件为true。相反，调用方应该在循环中等待：
// 
// c.L.Lock（）
// for！条件（）{
// c.等待（）
// }
// 。。。利用条件。。。
// c.L.Unlock（）
// 
func (c *Cond) Wait() {
	c.checker.check()
	t := runtime_notifyListAdd(&c.notify)
	c.L.Unlock()
	runtime_notifyListWait(&c.notify, t)
	c.L.Lock()
}

// 信号唤醒等待c的一个goroutine（如果有）。
// 
// 呼叫过程中允许但不要求呼叫方持有c.L 
// 。
func (c *Cond) Signal() {
	c.checker.check()
	runtime_notifyListNotifyOne(&c.notify)
}

// 广播唤醒所有等待c的goroutine。
// 
// 呼叫过程中允许但不要求呼叫方持有c.L 
// 。
func (c *Cond) Broadcast() {
	c.checker.check()
	runtime_notifyListNotifyAll(&c.notify)
}

// copyChecker保留指向自身的指针以检测对象复制。
type copyChecker uintptr

func (c *copyChecker) check() {
	if uintptr(*c) != uintptr(unsafe.Pointer(c)) &&
		!atomic.CompareAndSwapUintptr((*uintptr)(c), 0, uintptr(unsafe.Pointer(c))) &&
		uintptr(*c) != uintptr(unsafe.Pointer(c)) {
		panic("sync.Cond is copied")
	}
}

// 在第一次使用后，不得将复制内容嵌入结构中。
// 
// 参见https:
// 详细信息。
type noCopy struct{}

// 锁是“go vet”中的-copylocks检查器使用的不可操作的锁。
func (*noCopy) Lock()   {}
func (*noCopy) Unlock() {}
